package api

import (
	"ChdChat-Gin/model"
	"ChdChat-Gin/service"
	"ChdChat-Gin/utils"
	"fmt"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
)

func Login(c *gin.Context) {
	var loginBody model.UserAccounts
	if err := c.BindJSON(&loginBody); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"msg": fmt.Sprintf("Parameter format error, %v", err),
		})
		log.Printf("Login.BindJSON:%v\n", err)
		return
	}
	userInfo, token, err := service.LoginVerified(loginBody)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"msg": fmt.Sprintf("Failed to Login, %v", err),
		})
		log.Printf("Login.LoginVerified:%v\n", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"token":    token,
		"userInfo": userInfo,
		"msg":      "Login successfully",
	})
}

func Logout(c *gin.Context) {
	claims := c.MustGet("claims").(model.Claims)
	err := service.Logout(claims.RdsKey)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": fmt.Sprintf("Failed to Logout, %v", err),
		})
		log.Printf("Logout.Logout:%v\n", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"msg": "Logout successfully",
	})
}

func Register(c *gin.Context) {
	var registerBody model.UserAccounts
	if err := c.BindJSON(&registerBody); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"msg": fmt.Sprintf("Parameter format error, %v", err),
		})
		log.Printf("Register.BindJSON:%v\n", err)
		return
	}
	if err := utils.VerifyRegisterBody(registerBody); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"msg": fmt.Sprintf("Parameter error, %v", err),
		})
		log.Printf("Register.VerifyRegisterBody:%v\n", err)
		return
	}
	result, err := service.RegisterUer(registerBody)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": fmt.Sprintf("Failed to register, %v", err),
		})
		log.Printf("Register.RegisterUser:%v\n", err)
		return
	}
	if result > 0 {
		c.JSON(http.StatusOK, gin.H{
			"msg": "Register successfully",
		})
	}
}

func FetchContacts(c *gin.Context) {
	claims := c.MustGet("claims").(*model.Claims)
	relationship, contactList, groupList, err := service.FetchContacts(claims.Account)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": fmt.Sprintf("Failed to Fetch contact list, %v", err),
		})
		log.Printf("FetchContacts.FetchContacts:%v\n", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"groupList":    groupList,
		"contactList":  contactList,
		"relationship": relationship,
		"msg":          "Fetch contact list successfully",
	})
}

func FetchUserList(c *gin.Context) {
	claims := c.MustGet("claims").(*model.Claims)
	condition := c.Query("condition")
	userList, err := service.FetchUserList(claims.Account, condition)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": fmt.Sprintf("Failed to fetch user list, %v\n", err),
		})
		log.Printf("FetchUserList.FetchUserList:%v\n", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"userList": userList,
		"msg":      "Fetch contact list successfully",
	})
}

func FetchGroupList(c *gin.Context) {
	claims := c.MustGet("claims").(*model.Claims)
	condition := c.Query("condition")
	groupList, err := service.FetchGroupList(claims.Account, condition)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": fmt.Sprintf("Failed to fetch group list, %v", err),
		})
		log.Printf("FectGroupList.FetchGroupList:%v\n", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"msg":       "Fetch contact list successfully",
		"groupList": groupList,
	})
}

func AddContact(c *gin.Context) {
	var data model.ContactNotices
	if err := c.BindJSON(&data); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"msg": fmt.Sprintf("Parameter format error, %v", err),
		})
		log.Printf("AddContact.BindJSON:%v\n", err)
		return
	}
	if err := service.AddContact(data); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": fmt.Sprintf("Failed to Initiate application, %v", err),
		})
		log.Printf("AddContact.AddContact:%v\n", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"msg": "Initiate application successfully, wait for handle",
	})
}

func DeleteContact(c *gin.Context) {
	account := c.Query("account")
	if err := service.DeleteContact(account); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": fmt.Sprintf("Failed to delete contact, %v", err),
		})
		log.Printf("DeleteContact.DeleteContact:%v\n", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"msg": "DeleteContact successfully",
	})
}

func HandleNotice(c *gin.Context) {
	var data model.ContactNotices
	if err := c.BindJSON(&data); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"msg": fmt.Sprintf("Parameter format error, %v", err),
		})
		log.Printf("HandleNotice.BindJSON:%v\n", err)
		return
	}
	if err := service.HandleNotice(data); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": fmt.Sprintf("Failed to handle notice, %v", err),
		})
		log.Printf("HandleNotice.HandleNotice:%v\n", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"msg": "handle notice successfully",
	})
}

func FetchContactNotices(c *gin.Context) {
	claims := c.MustGet("claims").(*model.Claims)
	contactNotices, groupNotices, err := service.FetchContactNotices(claims.Account)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": fmt.Sprintf("Failed to fetch notices, %v", err),
		})
		log.Printf("FetchContactNotices.FetchContactNotices:%v\n", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"msg":            "Fetch notice list successfully",
		"contactNotices": contactNotices,
		"groupNotices":   groupNotices,
	})
}

func UpdateUserInfo(c *gin.Context) {
	var userInfo model.UserInfos
	if err := c.BindJSON(&userInfo); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"msg": fmt.Sprintf("Parameter format error, %v", err),
		})
		log.Printf("UpdateUserInfo.BindJSON:%v\n", err)
		return
	}
	if err := service.UpdateUserInfo(userInfo); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": fmt.Sprintf("Failed to update user info, %v", err),
		})
		log.Printf("UpdateUserInfo.UpdateUserInfo:%v\n", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"msg": "Update successfully",
	})
}

func FetchAvatarSrc(c *gin.Context) {
	source, err := service.FetchAvatarSrc()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": fmt.Sprintf("Failed to fetch avatar source, %v", err),
		})
		log.Printf("FetchAvatarSrc.FetchAvatarSrc:%v\n", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"msg":    "Fetch avatar source successfully",
		"source": source,
	})
}

func UploadAvatar(c *gin.Context) {
	file, err := c.FormFile("avatar-file")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"msg": fmt.Sprintf("Avatar source error, %v", err),
		})
		log.Printf("UploadAvatar.FormFile:%v\n", err)
		return
	}
	avatarURL, err := service.UploadAvatar(file, c)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": fmt.Sprintf("Failed to upload picture, %v", err),
		})
		log.Printf("UploadAvatar.UploadAvatar:%v\n", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"msg":       "Upload successfully",
		"avatarURL": avatarURL,
	})
}
